<!--
 * @Author: lmh
 * @Date: 2021-09-12 18:25:11
 * @LastEditTime: 2021-09-12 21:43:08
 * @LastEditors: lmh
 * @Description: 事件模型
-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <button id="btn">click</button>
    <script>
        // 全局的event对象， 提供on，off， emit方法
        var event = (function () {
            var eventObjs = {}

            return {
                // 注册事件 ，可以连续注册，可以注册多个事件
                on: function(type, handler) {
                    (eventObjs[type] || (eventObjs[type] = [])).push(handler)
                },

                // 移除事件
                //   如果没有参数，移除所有事件
                //   如果只带有 事件名 参数，就移除这个事件名下的所有事件
                //   如果带有两个参数，就表示移除某个事件的具体处理函数
                off: function(type, handler) {
                    if (arguments.length === 0) { // 移除所有事件
                        eventObjs = {}
                    } else if (arguments.length === 1) { // 移除该事件的所有处理函数
                        eventObjs[type] = {}
                    } else if (arguments.length === 2) { // 移除type事件的handler处理函数
                        let _events = eventObjs[type]
                        if (!_events) return
                        // 倒着循环数组， 序号不会受到影响
                        for (let i = _events.length-1; i >= 0; i--) {
                            if(_events[i] === handler) {
                                _events.splice(i, 1)
                            }
                        }
                    }
                },

                // 发射事件，触发事件，包装参数 传递给事件处理函数
                emit: function(type) {
                    let args = Array.prototype.slice.call(arguments, 1) // 获得从下标1开始后所有参数
                    let _events = eventObjs[type]
                    if(!_events) return
                    for(let i = 0; i < _events.length; i++) {
                        _events[i].apply(null, args)
                    }
                },
            }
        }())
    </script>
    <script>
        // 注册事件
        event.on('click', () => { console.log('第一个click事件') })
        console.log('1')
        function f() {
            event.emit('click')
        }
        f()
        // js基本类型 比较值
        // 引用类型比较地址
        // 引用类型与基本类型，是将其转换为 基本类型再比较 ， 如果是 === 严格等于是不转换比较
    </script>
    <script>
        var btn = document.querySelector('#btn')
        // // 注册
        // btn.addEventListener('click', function() {
        //     console.log('点击了')
        // })
        // // 移除
        // btn.removeEventListener('click', function() {
        //     console.log('点击了')
        // })
        // 还是不可移出
        
        // 如果可移除
        function handler() {
            console.log('可移除的事件处理函数')
        }
        btn.addEventListener('click', handler)
        // btn.removeEventListener('click', handler)
    </script>
</body>
</html>
